package com.jy.modules.cims.creditright.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.exception.CimsExceptionConstant;
import com.jy.modules.cims.common.sysUtils.CollectionsUtils;
import com.jy.modules.cims.common.sysUtils.SearchParamUtil;
import com.jy.modules.cims.common.sysUtils.SimpleStringUtils;
import com.jy.modules.cims.common.sysUtils.SpringContextUtils;
import com.jy.modules.cims.component.api.IJieYueSend;
import com.jy.modules.cims.component.credit.creditor.transferee.ICreditorTransfereeDeal;
import com.jy.modules.cims.component.credit.creditor.transferor.ICreditorTransferorDeal;
import com.jy.modules.cims.component.sysAssist.AbstractDueExecuteTaskManager;
import com.jy.modules.cims.component.sysAssist.BatchService;
import com.jy.modules.cims.contract.service.ContractService;
import com.jy.modules.cims.data.common.dto.TCMmCreditDealDetailDTO;
import com.jy.modules.cims.data.dao.CostPlanDao;
import com.jy.modules.cims.data.dao.CreditDealDetailDao;
import com.jy.modules.cims.data.dao.DealDao;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.DealDetailByCreditDto;
import com.jy.modules.cims.data.dto.DealDto;
import com.jy.modules.cims.data.dto.credit.CreditApplyDto;
import com.jy.modules.cims.data.dto.credit.CreditApplyResultDto;
import com.jy.modules.cims.data.dto.credit.SettleResult;
import com.jy.modules.cims.data.dto.credit.SettleResultDto;
import com.jy.modules.cims.data.interact.api.request.RequestNoiteCreditRedemptionDTO;
import com.jy.modules.cims.data.interact.api.request.RequestNoiteCreditRedemptionDetailDTO;
import com.jy.modules.cims.deal.service.DealService;
import com.jy.modules.cims.interact.CIRCreditPoolIFImpl;
import com.jy.modules.cims.interact.IInteractAssist;
import com.jy.modules.cims.recCreditRefundPlan.service.RecCreditRefundPlanService;
import com.jy.modules.cims.settle.service.SettleBalanceService;
import com.jy.modules.cims.settle.service.SettleService;
import com.jy.modules.cims.sysassist.SysAssistService;

/**
 * @description 债权处理服务层。
 * @author shengzhoutao
 * @date 2015-07-07
 */
@Service("com.jy.modules.cims.creditright.service.CreditDealService")
public class CreditDealService {
	private static final Logger logger = LoggerFactory.getLogger(CreditDealService.class);

	private final String TRANSFEREE_BEAN_NAME = "com.jy.modules.cims.component.credit.creditor.transferee.{0}CreditorTransfereeDeal";
	private final String TRANSFEREE_DEFAULT_BEAN_PREFIX = "General";

	private final String TRANSFEROR_BEAN_NAME = "com.jy.modules.cims.component.credit.creditor.transferor.{0}CreditorTransferorDeal";
	private final String TRANSFEROR_DEFAULT_BEAN_PREFIX = "General";

	private static final int DEFAULT_BATCH_COUNT = 10;// 每一次执行的条数
	private static final String METHOD_SENDSETTLEPLAN = "sendApplyResultToConsult";// 推送结算计划处理方法名

	/**
	 * 债权来源，类型转换 -核心
	 */
	private static HashMap<String, String> cdSouceMap = new HashMap<String, String>();
	static {
		 cdSouceMap.put(CimsConstant.CREDIT_SOURCE_CRE, "2");//债权转让
		 cdSouceMap.put(CimsConstant.CREDIT_SOURCE_REC, "1");//债权受让
		 cdSouceMap.put(CimsConstant.CREDIT_SOURCE_LOA, "3");//贷款
	}
	
	@Autowired
	private SpringContextUtils springContextUtils;

	@Autowired
	public DealDao dealDao;

	@Autowired
	@Qualifier("com.jy.modules.cims.deal.service.DealService")
	public DealService dealService;

	@Autowired
	@Qualifier("com.jy.modules.cims.creditright.service.CreditRightService")
	private CreditRightService creditRightService;

	@Autowired
	@Qualifier("com.jy.modules.cims.contract.service.ContractService")
	private ContractService contractService;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.component.sysAssist.DueExecuteTaskManager")
	public AbstractDueExecuteTaskManager abstractDueExecuteTaskManager;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CIRCreditPoolIFImpl")
	public CIRCreditPoolIFImpl cIRCreditPoolIFImpl;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CInteractAssist")
	private IInteractAssist iInteractAssist;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.sysassist.SysAssistService")
	private SysAssistService sysAssistService;

	@Autowired
	@Qualifier("com.jy.modules.cims.component.sysAssist.BatchService")
	public BatchService batchService;
	
	@Autowired
	private RecCreditRefundPlanService recCreditRefundPlanService;
	
	@Autowired
	private CreditDealDetailDao creditDealDetailDao;
	
	@Autowired
	private CostPlanDao costPlanDao;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.settle.service.SettleBalanceService")
	public SettleBalanceService settleBalanceService;
	
	@Autowired
	@Qualifier("jieYueSendService")
	private IJieYueSend jieYueSend;
	
	/**
	 * @description 新增债权受让，如果新增不需要传入交易流水号，但是实体对象其它属性的值都必须传入。<br>
	 *              新增债权受让，导入Excel文件，读取文件后 ，调用该方法。
	 * @param applyDto
	 *            债权申请实体
	 * @author shengzhoutao
	 * @date 2015-07-07
	 */
	public void doTransferee(CreditApplyDto applyDto) throws Exception {
		logger.info("====================新增债权受让 begin====================");

		contractService.checkCreditSettleParam(applyDto.getContractCode());
		
		String cooperorgCode = CimsConstant.COOPERORG_CODE_JY.equals(applyDto.getTransfereeCode()) ? applyDto.getTransferorCode() : applyDto
				.getTransfereeCode();

		ICreditorTransfereeDeal creditorTransfereeDeal = getTransBean(TRANSFEREE_BEAN_NAME, TRANSFEREE_DEFAULT_BEAN_PREFIX, cooperorgCode);
		ICreditorTransferorDeal creditorTransferorDeal = getTransBean(TRANSFEROR_BEAN_NAME, TRANSFEROR_DEFAULT_BEAN_PREFIX, cooperorgCode);

		// 创建请求
		creditorTransfereeDeal.createApply(applyDto);

		// 发送请求
		creditorTransfereeDeal.sendApplyToConsult(applyDto);

		// 获取数据结果
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("dataType", applyDto.getDataType());
		dataMap.put("dataId", applyDto.getDataId());
		dataMap.put("data", applyDto.getCreditDetailList());
		CreditApplyResultDto applyResultDto = creditorTransferorDeal.getMatchedResult(dataMap);

		// 确认结果
		creditorTransfereeDeal.confirmApplyResult(applyDto, applyResultDto);

		logger.info("====================新增债权受让 end====================");
	}

	/**
	 * @description 撤销债权受让请求，支持可以撤销多个请求。
	 * @param applyDtoList
	 *            多个债权申请实体的集合，申请实体的属性<code>dealCode</code>交易流水号必须传入值。
	 * @author shengzhoutao
	 * @date 2015-07-07
	 */
	public void doCancelApply(List<CreditApplyDto> applyDtoList) throws Exception {
		logger.info("====================撤销债权受让 begin====================");

		if (CollectionsUtils.isEmpty(applyDtoList)) {
			return;
		}

		for (CreditApplyDto applyDto : applyDtoList) {
			String cooperorgCode = CimsConstant.COOPERORG_CODE_JY.equals(applyDto.getTransfereeCode()) ? applyDto.getTransferorCode() : applyDto
					.getTransfereeCode();

			ICreditorTransfereeDeal creditorTransfereeDeal = getTransBean(TRANSFEREE_BEAN_NAME, TRANSFEREE_DEFAULT_BEAN_PREFIX, cooperorgCode);
			creditorTransfereeDeal.cancelApply(applyDto);
		}

		logger.info("====================撤销债权受让 end====================");
	}

	/**
	 * @description 发送债权受让申请结果。新增导入文件后，生成结算计划，并发送结算给核心系统，需要调用该方法。
	 * @param dealCode
	 *            交易流水号
	 * @author shengzhoutao
	 * @date 2015-07-07
	 */
	public void doSendApply(final String dealCode) throws Exception {
		logger.info("====================确认债权受让申请 begin====================");

		List<DealDto> dealDtoList = dealService.getCooperorgDealByDealCodeStr(dealCode);
		if (CollectionsUtils.isEmpty(dealDtoList)) {
			throw new Exception(MessageFormat.format("根据交易流水号[{0}]没有查询到该信息！", new Object[] { dealCode }));
		}

		DealDto dealDto = dealDtoList.get(0);
		if (!CimsConstant.DEAL_STATUS_CREATE.equals(dealDto.getCooperativeAgencyDealStatus())) {
			throw new Exception(MessageFormat.format("根据交易流水号[{0}]的交易状态不符合要求！", new Object[] { dealCode }));
		}
		if (!CimsConstant.DEAL_TYPE_CREDIT_IN.equals(dealDto.getDealType())) {
			throw new Exception(MessageFormat.format("根据交易流水号[{0}]的交易类型不符合要求！", new Object[] { dealCode }));
		}

		List<CreditDetailDto> creditDetailList = creditRightService.getCreditDetailByDealCode(dealCode);
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			throw new Exception(MessageFormat.format("根据交易流水号[{0}]没有查询到债权明细！", new Object[] { dealCode }));
		}

		// 生成结算计划
		recCreditRefundPlanService.beginRepaymentPlanToday(dealCode);
		
		// 发送结算计划
		boolean isFullCreatCostPlan = creditRightService.isFullCreatCostPlan(dealCode);
		if (isFullCreatCostPlan == false) {
			logger.info("根据交易流水号[{}]生成的结算计划不完整，不需要发送结算计划。", dealCode);
			throw new Exception(MessageFormat.format("根据交易流水号[{}]生成的结算计划不完整，不需要发送结算计划！", new Object[] { dealCode }));
		}
		Map<Object, Object> paramterMap = new HashMap<Object, Object>();
		paramterMap.put("dealCode", dealCode);
		paramterMap.put("cooperorgCode", dealDto.getCooperorgCode());
		batchService.batchInvoke(SettleService.class, METHOD_SENDSETTLEPLAN, creditDetailList, paramterMap, DEFAULT_BATCH_COUNT);
		
		// 修改交易流水的交易状态为在途
		List<String> dealCodeList = new ArrayList<String>();
		dealCodeList.add(dealCode);
		dealService.updateDealStatusByDealCodeList(CimsConstant.DEAL_STATUS_WAY, dealCodeList);

		dealCodeList = null;

		logger.info("====================确认债权受让申请 end====================");
	}

	/**
	 * @description 根据不同机构标示获取相关的组件
	 * @param transBean
	 * @param prefix
	 * 
	 * @param cooperorgCode
	 *            合作机构，用于区分不同机构业务的业务需求
	 * @return
	 * @author shengzhoutao
	 * @date 2015-07-07
	 */
	private <T> T getTransBean(final String transBean, final String prefix, final String cooperorgCode) {
		logger.info("transBean==>>" + transBean);
		logger.info("prefix==>>" + prefix);
		logger.info("cooperorgCode==>>" + cooperorgCode);

		String argument = SimpleStringUtils.hasText(cooperorgCode) ? cooperorgCode : prefix;

		T bean = null;
		String beanName = java.text.MessageFormat.format(transBean, new Object[] { argument });
		try {
			bean = springContextUtils.getBean(beanName);
		} catch (Exception e) {
			beanName = java.text.MessageFormat.format(transBean, new Object[] { prefix });
			bean = springContextUtils.getBean(beanName);
		}

		logger.info("业务Bean名称==>>" + bean.getClass().getName());
		return bean;
	}

	/**
	 * @description 根据流水查询债权受让在途债权，调用核心接口，获取处理状态。<br>
	 *              如果核心返回流水是已经结算，需要更新流水：交易已经完成；更新债权明细 ：已经已经确认。
	 * @author lizhenhuan
	 * @date 2015-08-13
	 */
	public void updateSettleResult() {
		// 校验核心日终状态
    	sysAssistService.checkCoreStatus() ;
    	
		DealDto dto = new DealDto();
		dto.setDealType(CimsConstant.DEAL_TYPE_CREDIT_IN);
		dto.setCooperativeAgencyDealStatus(CimsConstant.DEAL_STATUS_WAY);
		List<DealDto> dealcodes = dealService.getSettleResultList(SearchParamUtil.getSearchParam(dto));

		if (CollectionsUtils.isEmpty(dealcodes)) {
			return;
		}

		//DealDto dtoDealCode = new DealDto();
		SettleResult settleResult = null;

		for (DealDto dtoDealCode : dealcodes) {
			String busiNoForInteract = iInteractAssist.getInteractNo();
		//	dtoDealCode = dealcodes.get(i);
			String dealCode = dtoDealCode.getDealCode();
			settleResult = new SettleResult();
			settleResult.setDealCode(busiNoForInteract);
			settleResult.setApplyCode(dealCode);
			settleResult.setApplyType(CimsConstant.DEAL_SETTLE_TYPE);
			String settleStatus = "";
			try {
				SettleResultDto settleResultDto = cIRCreditPoolIFImpl.querySettleResultRepayment(settleResult);
				settleStatus = settleResultDto.getState();
			} catch (Exception e) {
				logger.info("结算申请编号：" + dealCode + e.getMessage());
				//e.printStackTrace();
			}

			try {
				if (CimsConstant.DEAL_SETTLE_STATUS.equals(settleStatus)) {
					dealService.updateCreditDeal(dealCode, CimsConstant.DEAL_STATUS_FINISH);
					dealService.updateCreditSettle(dealCode, CimsConstant.CREDIT_STATUS_WIN);
				}
			} catch (Exception e) {
				logger.info(CimsExceptionConstant.UPDATE_CREDIT_SETTLE_IF + e.getMessage());
				//e.printStackTrace();
				//throw new SysAssistException(CimsExceptionConstant.UPDATE_CREDIT_SETTLE_IF + e.getMessage());
			}
		}
	}
	
	/**
	 * 
	 * @Description   更新结算状态接口调整---最新代码 
	 * void  
	 * @throws
	 * @author zhangmi
	 * @date 2016-4-19
	 */
	public void settleResult(){
		//更新核心日终
//		sysAssistService.checkCoreStatus() ;
		
		//查询待发送的结算申请编号
		List<DealDetailByCreditDto> listAppCodes = creditDealDetailDao.getWaitSettleApplyCodes(SearchParamUtil.getSearchParam());
		if (CollectionsUtils.isEmpty(listAppCodes)) {
			return;
		}
		//开始执行
		for (DealDetailByCreditDto dealDetailByCreditDto : listAppCodes) {
			doSettleResultOneApplyCode(dealDetailByCreditDto);
		}
		//修改交易流水结算状态
		settleBalanceService.updateCooperorgDealCostState();
	}
	
	/**
	 * 根据结算编号更新结算状态
	 * @Description 
	 * @param dealDetailByCreditDto   
	 * void  
	 * @throws
	 * @author zhangmi
	 * @date 2016-4-19
	 */
	private void doSettleResultOneApplyCode(DealDetailByCreditDto dealDetailByCreditDto){
		try {
			String busiNoForInteract = iInteractAssist.getInteractNo();
			SettleResult settleResult = new SettleResult();
			String settleApplyCode = dealDetailByCreditDto.getSettleApplyId();
			settleResult.setDealCode(busiNoForInteract);
			settleResult.setApplyCode(settleApplyCode); //结算编号
			settleResult.setApplyType(cdSouceMap.get(dealDetailByCreditDto.getCreditSource()));//结算类型
			SettleResultDto settleResultDto = cIRCreditPoolIFImpl.querySettleResultRepayment(settleResult);
			if(settleResultDto==null){
				throw new Exception("显示某条债权信息在合作机构存在，在核心不存在或无效债权，后续应查明原因！");
			}
			String applyType = settleResultDto.getApplyType();
			String applyCode = settleResultDto.getApplyCode();
			String state = settleResultDto.getState();
			
			//持久化数据
			TCMmCreditDealDetailDTO dto = new TCMmCreditDealDetailDTO();
			dto.setCostState(state);
			dto.setSettleApplyId(applyCode);
			if("1".equals(applyType)){
				//债权受让
				// 1 未结算，2 已结算
				if (CimsConstant.DEAL_SETTLE_STATUS.equals(state)) {
					dealService.updateCreditDeal(applyCode, CimsConstant.DEAL_STATUS_FINISH);
					dealService.updateCreditSettle(applyCode, CimsConstant.CREDIT_STATUS_WIN);
				}
				//creditDealDetailDao.updateCreditDealCostStateByApplyCode(SearchParamUtil.getSearchParam(dto));
			}else if("204".equals(applyType)//转让结算
					||"208".equals(applyType)//转让赎回结算
					||"212".equals(applyType)//转让月还现金结算
					||"214".equals(applyType)//转让二次购买
					||"215".equals(applyType)){//转让债权结清现金结算
				creditDealDetailDao.updateCreditDealCostStateByApplyCode(SearchParamUtil.getSearchParam(dto));
			}else if("305".equals(applyType)//月还现金结算
					||"308".equals(applyType)//提前结清现金结算
					||"311".equals(applyType)//二次购买
					||"313".equals(applyType)){ //贷款回购结算
				creditDealDetailDao.updateCreditDealCostStateByApplyCode(SearchParamUtil.getSearchParam(dto));
			}else if("302".equals(applyType))//贷款转出结算
			{
				creditDealDetailDao.updateLoanCostStateByApplyCode(SearchParamUtil.getSearchParam(dto));
				creditDealDetailDao.updateLoanDealCostStateByApplyCode(SearchParamUtil.getSearchParam(dto));
			}
		} catch (Exception e) {
			logger.error("债权结算编号："+dealDetailByCreditDto.getSettleApplyId()+"，更新债权结算状态异常！"+e.getMessage());
			//e.printStackTrace();
		}
	}
	
	/**
	 * 重置结算计划，还款计划
	 * @Description 
	 * @param transferId
	 * @throws Exception   
	 * void  
	 * @throws
	 * @author zhangmi
	 * @date 2016-3-8
	 */
	public void restCostPlanByTransferId(String transferId) throws Exception{
		costPlanDao.deleteTCMmCostPlanByTransferId(transferId);
		costPlanDao.deleteTCMmRefundPlanByTransferId(transferId);
		recCreditRefundPlanService.beginRepaymentPlanTransferId(transferId);
	}
	
	/**
	 * 
	 * @Description 根据交易流水号获取，交易月还归属
	 * @param dealCode
	 * @return
	 * @throws Exception   
	 * List<DealDto>  
	 * @throws
	 * @author zhangmi
	 * @date 2016-5-14
	 */
	public List<DealDto>  getAffiliationByDealCode(String dealCode){
		try {
			DealDto dto = new DealDto();
			dto.setDealCode(dealCode);
			return creditDealDetailDao.getAffiliationByDealCode(SearchParamUtil.getSearchParam(dto));
		} catch (Exception e) {
			//e.printStackTrace();
			logger.error("根据交易流水号"+dealCode+"获取交易月还归属失败！");
		}
		return null;
	}
	/**
	 * 债权赎回-通知
	 * @author zhangmi
	 * @date  2017年1月17日
	 * @param dto
	 * @throws Exception
	 */
	public String doSendCreditRedemption(DealDto dto) throws Exception{
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("dto", dto);
		List<CreditDetailDto> resultList = dealDao.getDealDetailForLoanInfo(paramMap);
		RequestNoiteCreditRedemptionDTO content = new RequestNoiteCreditRedemptionDTO();
		List<RequestNoiteCreditRedemptionDetailDTO> creditList = new ArrayList<RequestNoiteCreditRedemptionDetailDTO>();
		//如果为空
		if(CollectionsUtils.isEmpty(resultList)){
			return "赎回列表为空！发送通知失败！";
		}
		for (CreditDetailDto creditDetailDto : resultList) {
			RequestNoiteCreditRedemptionDetailDTO requestNoiteCreditRedemptionDetailDTO = new RequestNoiteCreditRedemptionDetailDTO();
			requestNoiteCreditRedemptionDetailDTO.setCreditCode(creditDetailDto.getCreditCode());
			requestNoiteCreditRedemptionDetailDTO.setTransferId(creditDetailDto.getTransferId());
			requestNoiteCreditRedemptionDetailDTO.setRedeemStatus("01");//赎回成功
			creditList.add(requestNoiteCreditRedemptionDetailDTO);
		}
		content.setCreditList(creditList);
		jieYueSend.noticeCreditRedemption(dto.getCooperorgCode(), content);
		return "赎回通知发送完毕！";
	}
}
